package com.whynot.frame.basic.mybatis.config;


import com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS;
import com.whynot.frame.basic.mybatis.config.dynamic.DynamicDataSource;
import com.whynot.frame.basic.mybatis.config.properties.CoreDataSource;
import com.whynot.frame.basic.mybatis.config.properties.MutiDataSource;
import com.whynot.frame.basic.mybatis.interceptor.PagePlugin;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.*;

/**
 * 描述: MyBatis在SpringBoot下的基础配置:
 * 注意：暂时不使用
 * 作者: chenyao
 * 日期: 2018-01-30.
 * 项目名称: banke-boot-basic
 * 版本: 1.0.0
 * JDK: since 1.8
 */
@Deprecated
//@Configuration
//@EnableTransactionManagement(order = 3,proxyTargetClass = true) //加入事务注解
//@MapperScan(basePackages={"com.banke.frame.**.mapper"})
public class MyBatisConfig {

    private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    //多数据源多事务也在这里面处理

    @Value("${mybatis.type-aliases-package:true}")
    private String typeAliasesPackage;

    @Value("${spring.datasource2.url:true}")
    private String url2;



    @Autowired
    CoreDataSource coreDataSource;

    @Autowired
    MutiDataSource mutiDataSource;

    @Autowired
    PagePlugin pagePlugin;

    @Bean
    public SqlSessionFactory sqlSessionFactoryBean() throws Exception {

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        if(url2.equals("true")){
            sqlSessionFactoryBean.setDataSource(dataSource1());//绑定数据源
        }else{
            sqlSessionFactoryBean.setDataSource(dynamicDataSource());//绑定数据源
        }

        //配置映射路径
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setConfigLocation(
                resolver.getResource("classpath:mybatis/mybatis-config.xml"));//绑定spring-config.xml
        sqlSessionFactoryBean.setMapperLocations(
                resolver.getResources("classpath*:mybatis/mapper/*/*.xml"));//绑定mapper映射文件
        sqlSessionFactoryBean.setVfs(SpringBootVFS.class);
        VFS.addImplClass(SpringBootVFS.class);//解决myBatis下 不能嵌套jar文件的问题
        String basicPackage = ("true".equals(typeAliasesPackage))?typeAliasesPackage:"com.banke.frame.**.entities";
        sqlSessionFactoryBean.setTypeAliasesPackage(setTypeAliasesPackage(basicPackage));//指定基础包
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pagePlugin});

        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 核心数据源
     */
    private HikariDataSource coreDataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        coreDataSource.config(dataSource);
        return dataSource;
    }

    /**
     * 另一个数据源
     */
    private HikariDataSource read2DataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        coreDataSource.config(dataSource);
        mutiDataSource.config(dataSource);
        return dataSource;
    }

    //数据源1
    @Bean(name = "datasource1")
    @ConditionalOnExpression("'${spring.datasource2.url:true}'=='true'")
    public DataSource dataSource1() {
        return coreDataSource();
    }


    /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     * @return
     */
    @Bean(name = "dynamicDataSource")
    @ConditionalOnExpression("'${spring.datasource2.url:true}'!='true'")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(coreDataSource());
        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap();
        dsMap.put("datasource1", coreDataSource());
        dsMap.put("datasource2", read2DataSource());

        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }


    @PostConstruct
    public void initDataSourcde(){
        //根据application的配置判断是否加载数据源对象
        //如果加载数据源对象就为设置对象id
        //改造dynamicDataSource里面获取以及设置数据源的方法。
    }


    /**
     * 组装别名
     * @param typeAliasesPackage
     * @return
     */
    public static String setTypeAliasesPackage(String typeAliasesPackage) {
        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
                resolver);
        typeAliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(typeAliasesPackage)
                + "/" + DEFAULT_RESOURCE_PATTERN;
        try {
            List<String> result = new ArrayList<String>();
            Resource[] resources = resolver.getResources(typeAliasesPackage);
            if (resources != null && resources.length > 0) {
                MetadataReader metadataReader = null;
                for (Resource resource : resources) {
                    if (resource.isReadable()) {
                        metadataReader = metadataReaderFactory
                                .getMetadataReader(resource);
                        try {
                            result.add(Class
                                    .forName(
                                            metadataReader.getClassMetadata()
                                                    .getClassName())
                                    .getPackage().getName());
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if (result.size() > 0) {
                HashSet<String> h = new HashSet<String>(result);
                result.clear();
                result.addAll(h);
                typeAliasesPackage=String.join(",",(String[]) result.toArray(new String[0]));
                System.out.println(typeAliasesPackage);
            } else {
                throw new RuntimeException(
                        "mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:"
                                + typeAliasesPackage + "未找到任何包");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return typeAliasesPackage;
    }
}
